	#include "Renderer_PCH.h"
#include "Renderer.h"

/*--------------------------------------------------------------------------*/

IRenderer* g_Renderer = NULL;

/*--------------------------------------------------------------------------*/

CRenderer::CRenderer() :
	m_res_x(800),
	m_res_y(600)
{
	g_Shell->AddLuaFunction("CreateTexture", LuaFunc::CreateTexture);
	g_Shell->AddLuaFunction("CreateFramebuffer", LuaFunc::CreateFramebuffer);
	g_Shell->AddLuaFunction("BindFramebuffer", LuaFunc::BindFramebuffer);
	g_Shell->AddLuaFunction("RenderType", LuaFunc::RenderType);
	g_Shell->AddLuaFunction("RenderQuad", LuaFunc::RenderQuad);
	g_Shell->AddLuaFunction("CopyTexture", LuaFunc::CopyTexture);
	g_Shell->AddLuaFunction("ClearColor", LuaFunc::ClearColor);

	m_timer					= g_Kernel->CreateNewTimer();
	m_rendererEvents_mutex	= g_Kernel->CreateNewMutex();
	m_requests_mutex		= g_Kernel->CreateNewMutex();
	m_typeRenderers_mutex	= g_Kernel->CreateNewMutex();

	m_rendererStorageMgr	= new RendererStorageMgr();
	m_dynGeometryMgr		= new DynGeometryMgr();
	m_materialMgr			= new MaterialMgr();
	m_textMgr				= new TextMgr();
	m_postprocessMgr		= new PostprocessMgr();
	m_queueMgr				= new QueueMgr();
}

/*--------------------------------------------------------------------------*/

CRenderer::~CRenderer()
{
	delete m_queueMgr;
	delete m_postprocessMgr;
	delete m_textMgr;
	delete m_materialMgr;
	delete m_dynGeometryMgr;
	delete m_rendererStorageMgr;
	
	/*--------------------------------------------------------------------------*/

	delete m_typeRenderers_mutex;
	delete m_timer;
	delete m_rendererEvents_mutex;
	delete m_requests_mutex;
}

/*--------------------------------------------------------------------------*/

void DebugOutput(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, void* userParam)
{
	const char* typestr = NULL;
	const char* severitystr = NULL;

	switch (type) {
	case GL_DEBUG_TYPE_ERROR:
		typestr = "ERROR";
		break;
	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
		typestr = "DEPRECATED_BEHAVIOR";
		break;
	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
		typestr = "UNDEFINED_BEHAVIOR";
		break;
	case GL_DEBUG_TYPE_PORTABILITY:
		typestr = "PORTABILITY";
		break;
	case GL_DEBUG_TYPE_PERFORMANCE:
		typestr = "PERFORMANCE";
		break;
	case GL_DEBUG_TYPE_OTHER:
		typestr = "OTHER";
		break;
	}
	
	switch (severity){
	case GL_DEBUG_SEVERITY_LOW:
		severitystr = "LOW";
		break;
	case GL_DEBUG_SEVERITY_MEDIUM:
		severitystr = "MEDIUM";
		break;
	case GL_DEBUG_SEVERITY_HIGH:
		severitystr = "HIGH";
		break;
	}
	
	__Error("OpenGL debug output\nMessage: %s\nType: %s\nSeverity: %s\nId: %d\n", message, typestr, severitystr, id);
}

void CRenderer::InitializeOpenGL( int res_x, int res_y )
{
	m_res_x = res_x;
	m_res_y = res_y;

	uint result = glewInit();
	__Check(result == GLEW_OK);
	
	// setup GL
#ifdef _DEBUG
	glEnable(GL_DEBUG_OUTPUT);
	glDebugMessageCallback((GLDEBUGPROC) &DebugOutput, NULL);
#endif

	__Info("[RENDERER] Vendor: %s", glGetString(GL_VENDOR));
	__Info("[RENDERER] GPU: %s", glGetString(GL_RENDERER));
	__Info("[RENDERER] Context version: %s", glGetString(GL_VERSION));
	__Info("[RENDERER] GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));

	glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &m_openGLConstants[EOpenGLConstant::max_uniform_buffer_bindings]);
	glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &m_openGLConstants[EOpenGLConstant::uniform_buffer_offset_alignment]);
		
	__Check(GLEW_ARB_vertex_buffer_object);
	__Check(GLEW_ARB_vertex_array_object);

	/*--------------------------------------------------------------------------*/

	AddRequest(NULL, new TextureRequest(DATA_PATH "engine/texture/default.png"));
	AddRequest(NULL, new TextureRequest(DATA_PATH "engine/texture/normal.jpg"));
	AddRequest(NULL, new TextureRequest(DATA_PATH "engine/texture/grass1.jpg"));
	AddRequest(NULL, new TextureRequest(DATA_PATH "engine/texture/sand1.jpg"));
	AddRequest(NULL, new TextureRequest(DATA_PATH "engine/texture/rock1.jpg"));
	AddRequest(NULL, new TextureRequest(DATA_PATH "engine/texture/rock2.jpg"));
	AddRequest(NULL, new TextureRequest(DATA_PATH "engine/texture/rock3.jpg"));

	

	g_Shell->FileNow(DATA_PATH "engine/config/renderer.lua");
	AddRequest(NULL, new MaterialRequest(DATA_PATH "engine/material/default.mat"));
	AddRequest(NULL, new MaterialRequest(DATA_PATH "engine/material/postprocess.mat"));
	AddRequest(NULL, new MaterialRequest(DATA_PATH "engine/material/skydome.mat"));

	/*--------------------------------------------------------------------------*/
	

	GetDynGeometryMgr()->InitDynGeometryMgr();
	GetRendererStorageMgr()->InitRendererStorage();
	GetTextMgr()->InitTextMgr();
	GetMaterialMgr()->InitMaterialMgr();
	GetPostprocessMgr()->InitPostprocessMgr();
	GetQueueMgr()->InitQueueMgr();

	/*--------------------------------------------------------------------------*/

	m_modelMatrix				= (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("ModelMatrix",				EConst::Mat4, 1, this, 0)->GetPointer();
	m_modelViewMatrix			= (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("ModelViewMatrix",			EConst::Mat4, 1, this, 1)->GetPointer();
	m_modelViewProjectionMatrix = (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("ModelViewProjectionMatrix",EConst::Mat4, 1, this, 2)->GetPointer();
	m_viewMatrix				= (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("ViewMatrix",				EConst::Mat4, 1, this, 3)->GetPointer();
	m_projectionMatrix			= (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("ProjectionMatrix",		EConst::Mat4, 1, this, 4)->GetPointer();
	m_invViewProjectionMatrix	= (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("InvViewProjectionMatrix",	EConst::Mat4, 1, this, 5)->GetPointer();
	m_invProjectionMatrix		= (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("InvProjectionMatrix",		EConst::Mat4, 1, this, 6)->GetPointer();
	m_viewProjectionMatrix		= (GLM_MAT4x4*) GetRendererStorageMgr()->CreateConst("ViewProjectionMatrix",	EConst::Mat4, 1, this, 7)->GetPointer();

	m_cameraNear				= (float*) GetRendererStorageMgr()->CreateConst("CameraNear",					EConst::Float1, 1, NULL, 0)->GetPointer();
	m_cameraFar					= (float*) GetRendererStorageMgr()->CreateConst("CameraFar",					EConst::Float1, 1, NULL, 0)->GetPointer();
	m_cameraWorldPosition		= (glm::vec4*) GetRendererStorageMgr()->CreateConst("CameraWorldPosition",		EConst::Float4, 1, NULL, 0)->GetPointer();

	m_debugColor				= (glm::vec4*) GetRendererStorageMgr()->CreateConst("DebugColor",				EConst::Float4, 1, this, 99)->GetPointer();

	/*--------------------------------------------------------------------------*/

	m_uniform_Bumpmapping_TextureMultiplier_1f	= (float*) GetRendererStorageMgr()->CreateConst("Bumpmapping_TextureMultiplier", EConst::Float1, 1, NULL, 0)->GetPointer();
	m_uniform_Bumpmapping_Strength_1f			= (float*) GetRendererStorageMgr()->CreateConst("Bumpmapping_Strength", EConst::Float1, 1, NULL, 0)->GetPointer();
	m_uniform_ConstantColor_4f					= (glm::vec4*) GetRendererStorageMgr()->CreateConst("ConstantColor", EConst::Float4, 1, NULL, 0)->GetPointer();

	AddRequest(NULL, new FontRequest(DATA_PATH "engine/font/default.fnt"));

	glEnable(GL_PRIMITIVE_RESTART);
	glPrimitiveRestartIndex(0xffff);
}

/*--------------------------------------------------------------------------*/

void CRenderer::RenderFrame()
{
	m_timer->ResetTimer();

	if (m_requests.empty() == false)
	{
		m_requests_mutex->Lock();
		for (auto iter = m_requests.begin(); iter != m_requests.end();)
		{
			IRequest* request = (*iter).second;
			void* ret = request->DoRequest();
			
			if (ret)
			{
				if ((*iter).first)
				{
					*((*iter).first) = (void*) ret;
				}

				delete request;
				iter = m_requests.erase(iter);
			}
			else
			{
				__Error("[RENDERER] Failed to finalize request!");
				iter++;
			}
		}

		m_requests_mutex->Unlock();
	}

	m_rendererEvents_mutex->Lock();

	for (auto iter = m_rendererEvents.begin(); iter != m_rendererEvents.end(); ++iter)
	{
		(*iter)->CallEvent();
	}

	m_rendererEvents_mutex->Unlock();

	std::string msg = "Renderer: " + std::to_string(m_timer->GetTime_ms()) + " ms";
	g_UserInterface->AddMessage(msg);
}

/*--------------------------------------------------------------------------*/

void CRenderer::AddRequest(void** ret, IRequest* request)
{
	m_requests_mutex->Lock();
	m_requests.push_back(std::make_pair(ret, request));
	m_requests_mutex->Unlock();
}

/*--------------------------------------------------------------------------*/

void CRenderer::AddRendererEvent( IRendererEvent* event )
{
	m_rendererEvents_mutex->Lock();
	m_rendererEvents.push_back(event);
	m_rendererEvents_mutex->Unlock();
}

/*--------------------------------------------------------------------------*/

void CRenderer::AddTypeRenderer( ITypeRenderer* typerenderer, const std::string& name, uint arg )
{
	m_typeRenderers_mutex->Lock();
	
	auto iter = m_typeRenderers.find(name);

	if (iter == m_typeRenderers.end())
	{
		m_typeRenderers[name] = std::make_pair(arg, typerenderer);
	}
	else
	{
		__Crash("TypeRenderer already exists!");
	}

	m_typeRenderers_mutex->Unlock();
}

/*--------------------------------------------------------------------------*/

void CRenderer::GetTypeRenderer( const std::string& name, uint& arg, ITypeRenderer** type )
{
	auto iter = m_typeRenderers.find(name);

	if (iter != m_typeRenderers.end())
	{
		arg =  iter->second.first;
		*type = iter->second.second;
	}
	else
	{
		__Crash("TypeRenderer does not exists!");
	}
}

/*--------------------------------------------------------------------------*/

const SemanticInfo* CRenderer::GetSemanticInfo( const std::string& name)
{
	for (uint i = 0; i < sizeof(g_ShaderSemantic) / sizeof(g_ShaderSemantic[0]); ++i)
	{
		if (g_ShaderSemantic[i].m_name == name)
		{
			return &g_ShaderSemantic[i];
		}
	}

	return NULL;
}

/*--------------------------------------------------------------------------*/

const SemanticInfo* CRenderer::GetSemanticInfo( ESemantic::Type semantic )
{
	return &g_ShaderSemantic[semantic];
}

/*--------------------------------------------------------------------------*/

int CRenderer::GetResX()
{
	return m_res_x;
}

/*--------------------------------------------------------------------------*/

int CRenderer::GetResY()
{
	return m_res_y;
}

/*--------------------------------------------------------------------------*/

void CRenderer::ResetMatrices()
{
	*m_modelMatrix					= GLM_MAT4x4();
	*m_modelViewMatrix				= GLM_MAT4x4();
	*m_modelViewProjectionMatrix	= GLM_MAT4x4();
	*m_viewMatrix					= GLM_MAT4x4();
	*m_projectionMatrix				= GLM_MAT4x4();
	*m_invViewProjectionMatrix		= GLM_MAT4x4();
	*m_invProjectionMatrix			= GLM_MAT4x4();
}

/*--------------------------------------------------------------------------*/

void CRenderer::UpdateConst( uint arg )
{
	switch (arg)
	{
	case 0:		//modelMatrix
		{
			break;
		}
	case 1:		//modelViewMatrix:
		{
			*m_modelViewMatrix = *m_viewMatrix * *m_modelMatrix;
			break;
		}
	case 2:		//modelViewProjectionMatrix
		{
			*m_modelViewProjectionMatrix = *m_projectionMatrix * *m_viewMatrix * *m_modelMatrix;
			break;
		}
	case 3:		//viewMatrix
		{
			break;
		}
	case 4:		//projectionMatrix
		{
			break;
		}
	case 5:		//invViewProjectionMatrix
		{
			*m_invViewProjectionMatrix = glm::inverse(*m_projectionMatrix * *m_viewMatrix * *m_modelMatrix);
			break;
		}
	case 6:
		{
			*m_invProjectionMatrix = glm::inverse(*m_projectionMatrix);
			break;
		}
	case 7:		//viewProjectionMatrix
		{
			*m_viewProjectionMatrix = *m_projectionMatrix * *m_viewMatrix;
			break;
		}
	case 99:
		{
			float ticks = (glm::abs((int)(g_Kernel->GetTicks() % 10000) - 5000)) * 0.0002f;
			*m_debugColor = glm::vec4(ticks, 1.0f - ticks, 1.0f - ticks, 1.0f);
			break;
		}
	default:
		{
			break;
		}
	}
}

/*--------------------------------------------------------------------------*/

void CRenderer::BindMaterial(const RMaterial* material )
{
 	GetMaterialMgr()->Bind(material);
// 
// 	DynamicSurface* ds = GetDynGeometryMgr()->BeginGeometry(6, EVertex::Position0 | EVertex::TexCoord0);
// 
// 	ds->vPosition0()[0] = glm::vec3(20.0f, 20.0f, 0.0f);
// 	ds->vPosition0()[1] = glm::vec3(180.0f, 20.0f, 0.0f);
// 	ds->vPosition0()[2] = glm::vec3(180.0f, 180.0f, 0.0f);
// 
// 	ds->vTexcoord0()[0] = glm::vec2(0.0f, 0.0f);
// 	ds->vTexcoord0()[1] = glm::vec2(1.0f, 0.0f);
// 	ds->vTexcoord0()[2] = glm::vec2(0.0f, 1.0f);
// 
// 	ds->vPosition0()[3] = glm::vec3(50.0f, 220.0f, 0.0f);
// 	ds->vPosition0()[4] = glm::vec3(380.0f, 220.0f, 0.0f);
// 	ds->vPosition0()[5] = glm::vec3(800.0f, 600.0f, 0.0f);
// 
// 	ds->vTexcoord0()[3] = glm::vec2(0.0f, 0.0f);
// 	ds->vTexcoord0()[4] = glm::vec2(1.0f, 0.0f);
// 	ds->vTexcoord0()[5] = glm::vec2(0.0f, 1.0f);
// 
// 	RVertexArray* va = GetDynGeometryMgr()->EndGeometry();
// 	va->Bind();
// 	glDrawArrays(GL_TRIANGLES, 0, 6);
// 
// // 	/*--------------------------------------------------------------------------*/
// 
// 	GetTextMgr()->SetBackgroundColor(glm::vec4(1.0, 1.0, 1.0, 1.0));
// 	GetTextMgr()->SetTextColor(glm::vec4(1.0, 0.0, 0.0, 1.0));
// 	GetTextMgr()->WriteText(f, "Czerwony", glm::vec2(500, 500));
// 
// 	GetTextMgr()->SetTextColor(glm::vec4(0.0, 1.0, 0.0, 1.0));
// 	GetTextMgr()->WriteText(f, "Zielony", glm::vec2(500, 480));
// 
// 	GetTextMgr()->SetTextColor(glm::vec4(0.0, 0.0, 1.0, 1.0));
// 	GetTextMgr()->WriteText(f, "Niebieski", glm::vec2(500, 460));
//  
// 	GetTextMgr()->SetTextColor(glm::vec4(1.0, 1.0, 1.0, 1.0));
// 	GetTextMgr()->WriteText(f, "Bialy", glm::vec2(500, 440));
}

/*--------------------------------------------------------------------------*/

void CRenderer::SetModelMatrix( const GLM_MAT4x4& matrix )
{
	*m_modelMatrix = matrix;
}

/*--------------------------------------------------------------------------*/

DynGeometryMgr* CRenderer::GetDynGeometryMgr()
{
	return m_dynGeometryMgr;
}

/*--------------------------------------------------------------------------*/

RendererStorageMgr* CRenderer::GetRendererStorageMgr()
{
	return m_rendererStorageMgr;
}

/*--------------------------------------------------------------------------*/

PostprocessMgr* CRenderer::GetPostprocessMgr()
{
	return m_postprocessMgr;
}

/*--------------------------------------------------------------------------*/

TextMgr* CRenderer::GetTextMgr()
{
	return m_textMgr;
}

/*--------------------------------------------------------------------------*/

MaterialMgr* CRenderer::GetMaterialMgr()
{
	return m_materialMgr;
}

/*--------------------------------------------------------------------------*/

QueueMgr* CRenderer::GetQueueMgr()
{
	return m_queueMgr;
}

/*--------------------------------------------------------------------------*/

int CRenderer::GetOpenGLConstant( EOpenGLConstant::Type type )
{
	return m_openGLConstants[type];
}

/*--------------------------------------------------------------------------*/

float* CRenderer::GetModelMatrix()
{
#ifdef USE_GLM_SIMD
	return (float*) m_modelMatrix->Data;
#else
	return glm::value_ptr(*m_modelMatrix);
#endif
}

/*--------------------------------------------------------------------------*/

float* CRenderer::GetViewMatrix()
{
#ifdef USE_GLM_SIMD
	return (float*) m_viewMatrix->Data;
#else
	return glm::value_ptr(*m_viewMatrix);
#endif
}

/*--------------------------------------------------------------------------*/

float* CRenderer::GetProjectionMatrix()
{
#ifdef USE_GLM_SIMD
	return (float*) m_projectionMatrix->Data;
#else
	return glm::value_ptr(*m_projectionMatrix);
#endif
}

/*--------------------------------------------------------------------------*/

void CRenderer::Draw(const RVertexArray* vao, ETopology::Type type, uint vertices, uint instances, const RVertexArray* instvao )
{
	RVertexArray::Unbind();
	vao->Bind(instvao);

	GLenum gltype = GL_POINTS;

	switch (type)
	{
	case ETopology::Points:
		{
			gltype = GL_POINTS;
			break;
		}
	case ETopology::Lines:
		{
			gltype = GL_LINES;
			break;
		}
	case ETopology::Triangles:
		{
			gltype = GL_TRIANGLES;
			break;
		}
	case ETopology::TriangleStrip:
		{
			gltype = GL_TRIANGLE_STRIP;
			break;
		}
	}

	if (instances == 0)
	{
		if (vao->GetNumIndices())
		{
			m_renderStats.DrawElements++;
			glDrawElements(gltype, vao->GetNumIndices(), GL_UNSIGNED_SHORT, NULL);
		}
		else
		{
			m_renderStats.DrawArrays++;
			glDrawArrays(gltype, 0, vertices);
		}
	}
	else
	{
		if (vao->GetNumIndices())
		{
			m_renderStats.DrawElementsInstanced++;
			glDrawElementsInstanced(gltype, vao->GetNumIndices(), GL_UNSIGNED_SHORT, NULL, instances);
		}
		else
		{
			m_renderStats.DrawArraysInstanced++;
			glDrawArraysInstanced(gltype, 0, vertices, instances);
		}		
	}
}

/*--------------------------------------------------------------------------*/

void CRenderer::DrawOrigin(float length)
{
	DynamicSurface* ds = g_Renderer->GetDynGeometryMgr()->BeginGeometry(6, EVertex::Position0);

	ds->vPosition0()[0] = glm::vec3(-length, 0.0f, 0.0f);
	ds->vPosition0()[1] = glm::vec3(length, 0.0f, 0.0f);
	
	ds->vPosition0()[2] = glm::vec3(0.0f, length, 0.0f);
	ds->vPosition0()[3] = glm::vec3(0.0f, -length, 0.0f);
	
	ds->vPosition0()[4] = glm::vec3(0.0f, 0.0f, length);
	ds->vPosition0()[5] = glm::vec3(0.0f, 0.0f, -length);

	g_Renderer->GetDynGeometryMgr()->EndGeometryAndDraw(ETopology::Lines, 0, 6);
}

/*--------------------------------------------------------------------------*/

void CRenderer::SetEngineUniform( EEngineUniform::Type type, void* ptn )
{
	switch (type)
	{
	case EEngineUniform::Bumpmapping_Strength_1f:
		{
			*m_uniform_Bumpmapping_Strength_1f = *(float*)ptn;
			return;
		}
	case EEngineUniform::Bumpmapping_TextureMultiplier_1f:
		{
			*m_uniform_Bumpmapping_TextureMultiplier_1f = *(float*)ptn;
			return;
		}
	case EEngineUniform::ConstantColor_4f:
		{
			*m_uniform_ConstantColor_4f = *(glm::vec4*)ptn;
		}
	}
}

/*--------------------------------------------------------------------------*/

uint CRenderer::GetEngineUniformSize( EEngineUniform::Type type )
{
	switch(type)
	{
	case EEngineUniform::Bumpmapping_Strength_1f:
	case EEngineUniform::Bumpmapping_TextureMultiplier_1f:
		return sizeof(float);
	case EEngineUniform::ConstantColor_4f:
		return sizeof(glm::vec4);
	}

	__Crash(0);
}

/*--------------------------------------------------------------------------*/

void CRenderer::SetCamera( const GLM_MAT4x4& view, const GLM_MAT4x4& proj, float near, float far, const glm::vec3& position )
{
	*m_viewMatrix = view;
	*m_projectionMatrix = proj;
	*m_viewProjectionMatrix = *m_projectionMatrix * *m_viewMatrix;

	*m_cameraFar = far;
	*m_cameraNear = near;
	*m_cameraWorldPosition = glm::vec4(position, 0.0f);
}

/*--------------------------------------------------------------------------*/

void CRenderer::ResetRenderStats()
{
	m_renderStats.Reset();
}

/*--------------------------------------------------------------------------*/

const RStats& CRenderer::GetRenderStats()
{
	return m_renderStats;
}

/*--------------------------------------------------------------------------*/

void LuaFunc::CreateTexture( const std::string& name, int width, int height, const std::string& format )
{
	TextureRequest* request = new TextureRequest(name, width, height, format);
	g_Renderer->AddRequest(NULL, request);
}

/*--------------------------------------------------------------------------*/

void LuaFunc::CreateFramebuffer( const std::string& name, const std::string& textures )
{
	FramebufferRequest* request = new FramebufferRequest(name, textures);
	g_Renderer->AddRequest(NULL, request);
}

/*--------------------------------------------------------------------------*/

void LuaFunc::BindFramebuffer( const std::string& name, const std::string& clear )
{
	BindFramebufferEvent* event = new BindFramebufferEvent(name, clear);
	g_Renderer->AddRendererEvent(event);
}

/*--------------------------------------------------------------------------*/

void LuaFunc::RenderType( const std::string& type )
{
	RenderTypeEvent* event = new RenderTypeEvent(type);
	g_Renderer->AddRendererEvent(event);
}

/*--------------------------------------------------------------------------*/

void LuaFunc::RenderQuad( const std::string& matname )
{
	RenderQuadEvent* event = new RenderQuadEvent(matname);
	g_Renderer->AddRendererEvent(event);
}

/*--------------------------------------------------------------------------*/

void LuaFunc::CopyTexture( const std::string& name )
{
	CopyTextureEvent* event = new CopyTextureEvent(name);
	g_Renderer->AddRendererEvent(event);
}

/*--------------------------------------------------------------------------*/

void LuaFunc::ClearColor( float r, float g, float b, float a, char stencil, float depth )
{
	ClearColorEvent* event = new ClearColorEvent(r, g, b, a, stencil, depth);
	g_Renderer->AddRendererEvent(event);
}

/*--------------------------------------------------------------------------*/